﻿using System;
using System.Collections;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Grishko.DataTier;


namespace Ecopsy.Tools
{
    /// <summary>
    ///  Источник данных для древовидных структур
    ///  Строит источник для TreeView на основании TreeEntitySingle объекта 
    ///  и делегата занимающегося форматированием нод 
    /// </summary>

    public class F_TreeDataSource : HierarchicalDataSourceControl, IHierarchicalDataSource
    {
        private TreeEntitySingle _TreeEntitySingle;
        Func<TreeEntitySingle, Ecopsy.Tools.F_TreeDataSource.F_TreeDataSourceView.F_TreeHierarchyData> _fNodeFormatter;

        /// <summary>
        /// конструктор
        /// </summary>
        /// <param name="obj"> источник данных для дерева в виде TreeEntitySingle</param>
        /// <param name="fNodeFormatter"> указатель на функцию возвращающей объект занимающийся форматированием нод при прорисовке </param>
        public F_TreeDataSource(TreeEntitySingle obj, Func<TreeEntitySingle, Ecopsy.Tools.F_TreeDataSource.F_TreeDataSourceView.F_TreeHierarchyData> fNodeFormatter)
            : base()
        {
            _TreeEntitySingle = obj;
            _fNodeFormatter = fNodeFormatter;

        }        
        /// <summary>
        /// конструктор,при использовании этого конструктора - обязательно переопределить 
        /// Get_TreeEntitySingle, Get_NodeFormatter
        /// </summary>
        public F_TreeDataSource():base(){}

        protected F_TreeDataSourceView view = null;

        protected override HierarchicalDataSourceView GetHierarchicalView(string s)
        {
            if (null == view)
            {
                view = Get_TreeDataSourceView();
                view.RootNode = _TreeEntitySingle;
                view.NodeFormatter = _fNodeFormatter;

            }
            return view;

        }

        public virtual TreeEntitySingle Get_TreeEntitySingle()
        {
            return _TreeEntitySingle;
        }

        public virtual Func<TreeEntitySingle, Ecopsy.Tools.F_TreeDataSource.F_TreeDataSourceView.F_TreeHierarchyData> Get_NodeFormatter()
        {
            return _fNodeFormatter;
        }

        protected virtual F_TreeDataSourceView Get_TreeDataSourceView()
        {
            return new F_TreeDataSourceView();
        }
              
        
        public class F_TreeDataSourceView : HierarchicalDataSourceView
        {
            
            private TreeEntitySingle _Root;

            private Func<TreeEntitySingle, F_TreeHierarchyData> _NodeFormatter;

            public override IHierarchicalEnumerable Select()
            {

                TreeHierarchicalEnumerable fshe = new TreeHierarchicalEnumerable();

                fshe.Add(GetIHierarchyDataObj(_Root, _NodeFormatter));

                return fshe;

            }

            public virtual IHierarchyData GetIHierarchyDataObj(TreeEntitySingle obj, Func<TreeEntitySingle, F_TreeHierarchyData> GetFormatter)
            {
                return GetFormatter(obj);
            }

            public TreeEntitySingle RootNode
            {
                get
                { return _Root; }
                set { _Root = value; }
            }

            public Func<TreeEntitySingle, F_TreeHierarchyData> NodeFormatter
            {
                set { _NodeFormatter = value; }



            }

            public class TreeHierarchicalEnumerable : ArrayList, IHierarchicalEnumerable
            {
                public TreeHierarchicalEnumerable()
                    : base()
                {
                }

                public IHierarchyData GetHierarchyData(object enumeratedItem)
                {
                    return enumeratedItem as IHierarchyData;
                }
            }

            /// <summary>
            /// Базовый класс для форматирования нод
            /// В наследниках обязательно переопределять GetNewObj - возвращая экземпляр наследника
            /// </summary>
            public class F_TreeHierarchyData : IHierarchyData
            {             
                
                public F_TreeHierarchyData(TreeEntitySingle obj)
                {
                    _nd = obj;                
                }

                protected TreeEntitySingle _nd = null;

                public override string ToString()
                {
                    return string.Empty ;
                }


                public virtual bool HasChildren
                {
                    get
                    {
                        return _nd.ChildNodes.Count > 0;
                    }
                }

                public virtual string Path
                {
                    get
                    {
                        return string.Empty;

                    }
                }

                public virtual object Item
                {
                    get
                    {
                        return _nd;
                    }
                }

                public virtual string Type
                {
                    get
                    {
                        return "TreeEntitySingle" ;
                    }
                }

                public virtual IHierarchicalEnumerable GetChildren()
                {
                    TreeHierarchicalEnumerable fshe = new TreeHierarchicalEnumerable();

                    _nd.ChildNodes.Reset();
                    foreach (TreeEntitySingle n in _nd.ChildNodes)
                    {
                        fshe.Add(GetNewObj(n));

                    }
                    return fshe;
                }

                public virtual IHierarchyData GetParent()
                {
                    if (null == _nd.ParentNode) return null;
                    return new F_TreeHierarchyData(_nd.ParentNode);
                }
                public virtual F_TreeHierarchyData GetNewObj(TreeEntitySingle nd)
                {
                    return GetNewObj(nd);
                }
            }

        }
    }
}

